package com.heu.miaosha.controller;

import com.alibaba.druid.util.StringUtils;
import com.google.common.util.concurrent.RateLimiter;
import com.heu.miaosha.error.BusinessException;
import com.heu.miaosha.error.EmBusinessError;
import com.heu.miaosha.mq.MqProducer;
import com.heu.miaosha.response.CommonReturnType;
import com.heu.miaosha.service.ItemService;
import com.heu.miaosha.service.OrderService;
import com.heu.miaosha.service.PromoService;
import com.heu.miaosha.service.model.OrderModel;
import com.heu.miaosha.service.model.UserModel;
import com.heu.miaosha.util.CodeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author: lidong
 * @description
 * @date: 2023/3/7 11:33
 */
@Controller
@RequestMapping("/order")
@Slf4j
//跨域请求
@CrossOrigin(origins = "http://localhost:63342",allowCredentials = "true",allowedHeaders = "*")
public class OrderController extends BaseController{
    @Autowired
    private OrderService orderService;


    @Autowired
    private HttpServletRequest httpServletRequest;


    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private MqProducer mqProducer;

    @Autowired
    private ItemService itemService;

    @Autowired
    private PromoService promoService;

    private ExecutorService executorService;

    private RateLimiter orderCreateRateLimiter;
    @PostConstruct
    public void init(){
        executorService = Executors.newFixedThreadPool(20);
        orderCreateRateLimiter = RateLimiter.create(300);
    }



    @RequestMapping(method = RequestMethod.POST,value = "/generatetoken",consumes = CONTENT_TYPE_FORMED)
    @ResponseBody
    public CommonReturnType generatetoken(@RequestParam(name = "itemId")Integer itemId,
                                       @RequestParam(name = "promoId")Integer promoId,
                                          @RequestParam(name = "verifyCode")String verifyCode) throws BusinessException {
        String token = httpServletRequest.getParameterMap().get("token")[0];
        if (StringUtils.isEmpty(token)){
            throw new BusinessException(EmBusinessError.USER_NOT_LOGIN,"用户还未登陆，不能下单");
        }


        UserModel loginUser = (UserModel)redisTemplate.opsForValue().get(token);

        if (loginUser == null){
            throw new BusinessException(EmBusinessError.USER_NOT_LOGIN,"用户还未登陆，不能下单");
        }
        //验证码的有效性
        String redisVerifyCode = (String) redisTemplate.opsForValue().get("verity_code_"+loginUser.getId());
        if (StringUtils.isEmpty(redisVerifyCode)){
            throw new BusinessException(EmBusinessError.UNKNOW_ERROR,"请求非法");
        }
        if (!redisVerifyCode.equalsIgnoreCase(verifyCode)){
            throw new BusinessException(EmBusinessError.UNKNOW_ERROR,"验证码错误");
        }



        //获取秒杀访问令牌
        String promoToken = promoService.generateSecondKillToken(promoId, itemId, loginUser.getId());

        if (promoToken == null){
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,"生成令牌失败");
        }

     return CommonReturnType.create(promoToken);
    }


    //验证码生成
    @RequestMapping(method = {RequestMethod.POST,RequestMethod.GET},value = "/generateverifycode")
    @ResponseBody
    public CommonReturnType generateverifycode(HttpServletResponse response) throws BusinessException, IOException {



        String token = httpServletRequest.getParameterMap().get("token")[0];
        if (StringUtils.isEmpty(token)){
            throw new BusinessException(EmBusinessError.USER_NOT_LOGIN,"用户还未登陆，不能下单");
        }
        UserModel loginUser = (UserModel)redisTemplate.opsForValue().get(token);

        if (loginUser == null){
            throw new BusinessException(EmBusinessError.USER_NOT_LOGIN,"用户还未登陆，不能下单");
        }
        Map<String,Object> map = CodeUtil.generateCodeAndPic();
        redisTemplate.opsForValue().set("verity_code_"+loginUser.getId(),map.get("code"));
        redisTemplate.expire("verity_code_"+loginUser.getId(),10,TimeUnit.MINUTES);
        ImageIO.write((RenderedImage) map.get("codePic"), "jpeg", response.getOutputStream());


        return CommonReturnType.create(null);

    }


    @RequestMapping(method = RequestMethod.POST,value = "/createorder",consumes = CONTENT_TYPE_FORMED)
    @ResponseBody
    public CommonReturnType creatOrder(@RequestParam(name = "itemId")Integer itemId,
                                       @RequestParam(name = "amount")Integer amount,
                                       @RequestParam(name = "promoId",required = false)Integer promoId,
                                       @RequestParam(name = "promoToken",required = false)String promoToken) throws BusinessException {

//        Boolean isLogin = (Boolean) this.httpServletRequest.getSession().getAttribute("IS_LOGIN");
        //令牌桶
        if(!orderCreateRateLimiter.tryAcquire()){
            throw new BusinessException(EmBusinessError.RATE_LIMIT);
        }
        String token = httpServletRequest.getParameterMap().get("token")[0];
        if (StringUtils.isEmpty(token)){
            throw new BusinessException(EmBusinessError.USER_NOT_LOGIN,"用户还未登陆，不能下单");
        }


        UserModel loginUser = (UserModel)redisTemplate.opsForValue().get(token);

        if (loginUser == null){
            throw new BusinessException(EmBusinessError.USER_NOT_LOGIN,"用户还未登陆，不能下单");
        }
        if (promoId != null){
            String inRedisPromoToken = (String) redisTemplate.opsForValue().get("promo_token_"+promoId+"_userid_"+loginUser.getId()+"_itemid_"+itemId);
            if (inRedisPromoToken == null){
                throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,"秒杀令牌获取失败");
            }
            if (!org.apache.commons.lang3.StringUtils.equals(promoToken,inRedisPromoToken)){
                throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,"秒杀令牌校验失败");
            }
        }



//        if(isLogin == null || !isLogin.booleanValue()){
//            throw new BusinessException(EmBusinessError.USER_NOT_LOGIN,"用户还未登陆，不能下单");
//        }
//        UserModel loginUser = (UserModel) httpServletRequest.getSession().getAttribute("LOGIN_USER");



//        OrderModel orderModel = orderService.creatOrder(loginUser.getId(), itemId,promoId, amount);



        Future<Object> future = executorService.submit(new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                String stockLogId = itemService.initStockLog(itemId,amount);

                if (!mqProducer.transactionAsyncReduceStock(itemId,amount, loginUser.getId(),promoId,stockLogId)){
                    throw new BusinessException(EmBusinessError.UNKNOW_ERROR,"下单失败");
                }

                return null;
            }
        });

        try {
            future.get();
        } catch (InterruptedException e) {
            throw new BusinessException(EmBusinessError.UNKNOW_ERROR);
        } catch (ExecutionException e) {
            throw new BusinessException(EmBusinessError.UNKNOW_ERROR);
        }
        //加入库存流水init状态
        return CommonReturnType.create(null);
    }
}
